package com.globallogic.javatrainings.sergiiivanov.model;

import java.io.Serializable;

import com.globallogic.javatrainings.sergiiivanov.resources.ErrorCodes;

/**
 * Used as a storage for buildings within university<br>
 * typical usage {@link University#buildings university.buildings...}<br>
 * Keeps collection of building as {@link MyArray}&lt;{@link Building}&gt;<br>
 * </table>
 * 
 * @author Sergey
 * 
 */
public class BuildingsManager implements Serializable {
    private static final long serialVersionUID = 1L;
    private MyArray<Building> buildings;

    /**
     * Creates new manager an binds it to {@link University}
     */
    public BuildingsManager() {
        buildings = new MyArray<Building>(new Building[0]);
    }

    /**
     * Adds new {@link Building} into collection in case when name is
     * {@link NameUniqueObserver unique} for the collection<br>
     * 
     * @param name
     *            - not empty unique name for the collection
     * @throws UniversityWarning
     *             when name is not valid
     */
    public void addBuilding(String name) throws UniversityWarning {
        if (name == null || Const.STRING_EMPTY.equals(name))
            throw new UniversityWarning(ErrorCodes.BUILDING_NAME_NULL);
        Building newBuilding = new Building();
        newBuilding.setManager(this);
        newBuilding.setName(name);
        buildings.add(newBuilding);
    }

    /**
     * Counts buildings
     * 
     * @return number of {@link #addBuilding(String) added} buildings
     */
    public int countBuildings() {
        if (buildings == null) {
            return 0;
        }
        return buildings.size();
    }

    /**
     * Returns {@link MyArray#copy() copy()} of buildings collection as
     * {@link MyArray}&lt;{@link Building}&gt;
     * 
     * @return {@link MyArray} of {@link Building}
     */
    public MyArray<Building> getBuildings() {
        return buildings.copy();
    }

    /**
     * Removes building from collection.<br>
     * You need to get building before by using {@link #getBuildings()} or
     * {@link #getBuildingByIndex(int)}
     * 
     * @param b
     *            {@link Building}
     * @throws UniversityFailure
     *             application crash
     * @throws UniversityWarning
     *             building not in collection or could not be removed due to
     *             unresolved links
     */
    public void removeBuilding(Building b) throws UniversityWarning {
        if (b != null && buildings.indexOf(b) > -1) {
            b.removeLinks();
            buildings.remove(b);
        } else {
            throw new UniversityWarning(ErrorCodes.BUILDING_NOT_FOUND);
        }
    }

    /**
     * Returns building stored in collection under provided index.
     * 
     * @param index
     *            valid index
     * @return {@link Building}
     * @throws UniversityFailure
     *             application crash
     * @throws UniversityWarning
     *             wrong index provided
     */
    public Building getBuildingByIndex(int index) throws UniversityFailure, UniversityWarning {
        if (index < 0 || countBuildings() <= index) {
            throw new UniversityWarning(ErrorCodes.BUILDING_NOT_FOUND_BY_INDEX + index);
        }
        return buildings.get(index);
    }

    /**
     * Used by Building in {@link Building#setName(String)} and validates if
     * provided name is not present in the collection<br>
     * Do not use it for names of buildings present in collection - result will
     * be positive as it will find itself
     * 
     * @param name
     *            validated name of the building
     * @throws UniversityWarning
     *             when name is found in collection
     */
    public void hasDuplicates(String name) throws UniversityWarning {
        for (Building b : buildings) {
            if (b.getName().equals(name)) {
                throw new UniversityWarning(ErrorCodes.BUILDING_NAME_NOT_UNIQUE + name);
            }
        }
    }
}
